package cn.iocoder.yudao.module.system.util;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 科目选择工具类
 * 用于根据省份和年份获取对应的科目选择类型
 */
@Slf4j
public class SubjectSelectionUtils {

    /**
     * 缓存解析后的JSON数据
     */
    private static final Map<String, Map<String, List<String>>> PROVINCE_YEAR_TYPE_CACHE = new ConcurrentHashMap<>();
    
    /**
     * 是否已初始化
     */
    private static boolean initialized = false;
    
    /**
     * 初始化加载JSON数据
     */
    private static synchronized void initialize() {
        if (initialized) {
            return;
        }
        
        try {
            // 读取JSON文件
            ClassPathResource resource = new ClassPathResource("subjectSelections.json");
            InputStream inputStream = resource.getInputStream();
            String jsonContent = IoUtil.read(inputStream, StandardCharsets.UTF_8);
            
            // 解析JSON
            JsonNode rootNode = JsonUtils.parseTree(jsonContent);
            JsonNode dataNode = rootNode.get("Data");
            
            if (dataNode == null) {
                log.error("Failed to parse subjectSelections.json: Data node not found");
                return;
            }
            
            // 遍历所有省份
            dataNode.fieldNames().forEachRemaining(province -> {
                JsonNode provinceNode = dataNode.get(province);
                Map<String, List<String>> yearTypeMap = new HashMap<>();
                
                // 遍历该省份的所有年份
                provinceNode.fieldNames().forEachRemaining(year -> {
                    JsonNode yearNode = provinceNode.get(year);
                    List<String> types = new ArrayList<>();
                    
                    // 获取该年份的所有类型
                    for (int i = 0; i < yearNode.size(); i++) {
                        JsonNode typeNode = yearNode.get(i);
                        String typeName = typeNode.get("name").asText();
                        types.add(typeName);
                    }
                    
                    yearTypeMap.put(year, types);
                });
                
                PROVINCE_YEAR_TYPE_CACHE.put(province, yearTypeMap);
            });
            
            initialized = true;
            log.info("Successfully loaded subjectSelections.json with {} provinces", PROVINCE_YEAR_TYPE_CACHE.size());
        } catch (IOException e) {
            log.error("Failed to load subjectSelections.json", e);
        }
    }
    
    /**
     * 根据省份、年份和首选科目获取科目选择类型
     * 
     * @param province 省份
     * @param year 年份
     * @param secondSuject 首选科目
     * @return 科目选择类型
     */
    public static String getSubjectSelectionType(String province, String year, String secondSuject) {
        if (!initialized) {
            initialize();
        }
        
        if (StrUtil.isBlank(province) || StrUtil.isBlank(year)) {
            return getDefaultType(secondSuject);
        }
        
        // 获取省份对应的年份-类型映射
        Map<String, List<String>> yearTypeMap = PROVINCE_YEAR_TYPE_CACHE.get(province);
        if (yearTypeMap == null) {
            log.warn("Province {} not found in subjectSelections.json", province);
            return getDefaultType(secondSuject);
        }
        
        // 获取年份对应的类型列表
        List<String> types = yearTypeMap.get(year);
        if (types == null || types.isEmpty()) {
            // 如果找不到指定年份，尝试使用最新年份的数据
            String latestYear = getLatestYear(yearTypeMap);
            if (latestYear != null) {
                log.info("Year {} not found for province {}, using latest year {} instead", year, province, latestYear);
                types = yearTypeMap.get(latestYear);
            }
            
            if (types == null || types.isEmpty()) {
                log.warn("No types found for province {} and year {}", province, year);
                return getDefaultType(secondSuject);
            }
        }
        
        // 如果只有一种类型，直接返回
        if (types.size() == 1) {
            return types.get(0);
        }
        
        // 根据首选科目确定类型
        if (secondSuject != null) {
            // 检查是否有物理类/历史类
            boolean hasPhysicsType = types.contains("物理类");
            boolean hasHistoryType = types.contains("历史类");
            
            if (hasPhysicsType && hasHistoryType) {
                if (secondSuject.contains("物理")) {
                    return "物理类";
                } else if (secondSuject.contains("历史")) {
                    return "历史类";
                }
            }
            
            // 检查是否有理科/文科
            boolean hasScienceType = types.contains("理科");
            boolean hasLiberalArtsType = types.contains("文科");
            
            if (hasScienceType && hasLiberalArtsType) {
                if (secondSuject.contains("物理")) {
                    return "理科";
                } else if (secondSuject.contains("历史")) {
                    return "文科";
                }
            }
            
            // 检查是否有综合
            if (types.contains("综合")) {
                return "综合";
            }
        }
        
        // 默认返回列表中的第一个类型
        return types.get(0);
    }
    
    /**
     * 获取最新的年份
     * 
     * @param yearTypeMap 年份-类型映射
     * @return 最新年份
     */
    private static String getLatestYear(Map<String, List<String>> yearTypeMap) {
        return yearTypeMap.keySet().stream()
                .max(String::compareTo)
                .orElse(null);
    }
    
    /**
     * 获取默认类型
     * 
     * @param firstSubject 首选科目
     * @return 默认类型
     */
    private static String getDefaultType(String firstSubject) {
        if (firstSubject != null) {
            if (firstSubject.contains("物理")) {
                return "物理类";
            } else if (firstSubject.contains("历史")) {
                return "历史类";
            }
        }
        return "物理类"; // 默认返回物理类
    }

    /**
     * 检查用户选科是否满足专业要求
     *
     * @param userSubjects 用户选科列表
     * @param requirement 专业选科要求
     * @return 是否匹配
     */
    public static boolean checkSubjectMatch(List<String> userSubjects, String requirement) {
        if (StrUtil.isBlank(requirement) || "不限".equals(requirement) || "无要求".equals(requirement)) {
            return true; // 没有选科要求或不限选科
        }

        if (userSubjects == null || userSubjects.isEmpty()) {
            return false; // 用户没有选科但专业有要求
        }

        // 将用户选科转换为标准化格式
        List<String> normalizedUserSubjects = new ArrayList<>();
        for (String subject : userSubjects) {
            normalizedUserSubjects.add(normalizeSubject(subject.trim()));
        }

        // 处理选科要求
        return parseAndCheckRequirement(normalizedUserSubjects, requirement);
    }

    /**
     * 解析并检查选科要求
     */
    private static boolean parseAndCheckRequirement(List<String> userSubjects, String requirement) {
        requirement = requirement.trim();

        // 处理"或"的情况（用"或"、"|"、"/"分隔）
        if (requirement.contains("或") || requirement.contains("|") || requirement.contains("/")) {
            String[] orOptions = requirement.split("[或|/]");
            for (String option : orOptions) {
                if (checkSingleRequirement(userSubjects, option.trim())) {
                    return true; // 满足任一选项即可
                }
            }
            return false;
        }

        // 处理单一要求
        return checkSingleRequirement(userSubjects, requirement);
    }

    /**
     * 检查单一选科要求
     */
    private static boolean checkSingleRequirement(List<String> userSubjects, String requirement) {
        requirement = requirement.trim();

        // 处理"且"、"和"、"+"的情况（需要同时满足）
        if (requirement.contains("且") || requirement.contains("和") || requirement.contains("+")) {
            String[] andRequirements = requirement.split("[且和+]");
            for (String andReq : andRequirements) {
                String subject = normalizeSubject(andReq.trim());
                if (!userSubjects.contains(subject)) {
                    return false; // 必须全部满足
                }
            }
            return true;
        }

        // 处理逗号分隔的情况（通常表示"或"的关系）
        if (requirement.contains(",") || requirement.contains("，")) {
            String[] subjects = requirement.split("[,，]");
            for (String subject : subjects) {
                String normalizedSubject = normalizeSubject(subject.trim());
                if (userSubjects.contains(normalizedSubject)) {
                    return true; // 满足任一即可
                }
            }
            return false;
        }

        // 单一科目要求
        String normalizedSubject = normalizeSubject(requirement);
        return userSubjects.contains(normalizedSubject);
    }

    /**
     * 标准化科目名称
     */
    private static String normalizeSubject(String subject) {
        if (StrUtil.isBlank(subject)) {
            return subject;
        }

        subject = subject.trim();

        // 处理常见的科目名称变体
        switch (subject) {
            case "物":
            case "物理学":
                return "物理";
            case "化":
            case "化学学":
                return "化学";
            case "生":
            case "生物学":
                return "生物";
            case "政":
            case "思想政治":
            case "政治学":
                return "政治";
            case "史":
            case "历史学":
                return "历史";
            case "地":
            case "地理学":
                return "地理";
            case "技":
            case "信息技术":
                return "技术";
            default:
                return subject;
        }
    }
}
